home *** CD-ROM | disk | FTP | other *** search
/ Plug-In Power Pack for Netscape Communicator / Plug-In Power Pack for Netscape Communicator.iso / plugins / dataviews / dvtools / examples / windows / mfc_mdi / mfc_mdiview.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-16  |  14.8 KB  |  452 lines

  1. // mfc_mdiView.cpp : implementation of the CMfc_mdiView class
  2. //
  3.  
  4. /////////////////////////////////////////////////////////////////////////////
  5. //
  6. //    DataViews Multiple Document Inteface (MDI) example program.
  7. //
  8. //    CMfc_mdiView class
  9. //    ------------------
  10. //
  11. //    The simplest way to imagine integrating DataViews into the MFC Document-
  12. //    View architecture is to first think of the DataViews view file as really
  13. //    belonging the CDocument (and with that, an unfortunate clash of nomencla-
  14. //    ture!), and the DataView's screen and drawport as belonging more naturally
  15. //    with the MFC CView.
  16. //
  17. //    The CMfc_mdiView class then is responsible for creating the DataViews
  18. //    screen and drawport used to display the view, updating dynamics (indirect-
  19. //    ly through a TimerProc), and repairing the screen when it is resized, or
  20. //    or partially obscured, or deiconified.
  21. //
  22. //    The InitDv() method gets called by the CDocument and gets passed in the
  23. //  view that was loaded.  It creates a DataViews screen object by calling 
  24. //    TscOpenSet() and passing in the window handle (from GetSafeHwnd).  Doing
  25. //    this tells the TscOpenSet() routine to create a DataViews screen object 
  26. //    using the window handle supplied rather than creating its own.  In DataViews
  27. //    parlance, this is called "creating a screen with an externally created
  28. //    window."
  29. //
  30. //    Once the screen object is created, the rest of the code is basic DataViews
  31. //    boilerplate code: the drawport is created, the view's data sources are 
  32. //    opened and and the first iteration of data read, the drawport is drawn
  33. //    initially, and then SetTimer() is called to set up a timerproc which will
  34. //    be used to continously update the view's dynamic objects.
  35. //
  36. //  In addition, there are message handlers for handling specific user interaction,
  37. //  namely WM_MOUSEMOVE, WM_LBUTTONDOWN and WM_LBUTTONDBLCLK messages.  The
  38. //  table below shows how you can see the results of these interactions:
  39. //
  40. //        Message          View Name               Interaction Seen by:
  41. //  ----------------------------------------------------------------------------
  42. //     WM_MOUSEMOVE        view3.v         moving the mouse over the slider
  43. //     WM_LBUTTONDOWN      view1.v         clicking on the toggle input object
  44. //     WM_LBUTTONDBLCLK   <all views>      double click on any DataViews object
  45. //
  46. //
  47. //  In addition to these, there are message handlers for the WM_ACTIVATE,
  48. //  WM_PALETTECHANGED, and WM_QUERYNEWPALETTE messages for handling color palette
  49. //  changes.
  50.  
  51. //    When the user closes the view, the OnDestroy() messages kills the timer,
  52. //    and the CMfc_mdiView's destructor destroys the drawport and closes (de-
  53. //    stroys the screen).
  54. //
  55. //    The OnDraw() method redraws the screen any time the screen needs to be
  56. //    all or partially redrawn.
  57. //
  58. /////////////////////////////////////////////////////////////////////////////
  59.  
  60.  
  61. #include "stdafx.h"
  62. #include "mfc_mdi.h"
  63. #include "mfc_mdiDoc.h"
  64. #include "mfc_mdiView.h"
  65.  
  66. #ifdef _DEBUG
  67. #define new DEBUG_NEW
  68. #undef THIS_FILE
  69. static char THIS_FILE[] = __FILE__;
  70. #endif
  71.  
  72.  
  73. /////////////////////////////////////////////////////////////////////////////
  74. //
  75. //    UpdateDynamicsTimerProc()
  76. //
  77. //    TimerProc callback function. This routine gets called whenever the time
  78. //    interval has expired (see SetTimer).  It casts the nIDEvent parameter to
  79. //    be a pointer to a CMfc_mdiView object (effectively the 'this' pointer in
  80. //    this module-- see the InstallTimer() method below) and uses that to call
  81. //    the DataViews routines TviReadData() to get the next iteration of data
  82. //    and TdpDrawNext() to update the screen.
  83. //
  84. void CALLBACK EXPORT UpdateDynamicsTimerProc(
  85.    HWND hWnd,      //handle of CWnd that called SetTimer
  86.    UINT nMsg,      //WM_TIMER
  87.    UINT nIDEvent,  //timer identification
  88.    DWORD dwTime    //system time
  89. )
  90. {
  91.     CMfc_mdiView* pView = (CMfc_mdiView*)nIDEvent;
  92.  
  93.     TviReadData(pView->GetDocument()->GetDVview());
  94.     TdpDrawNext(pView->GetDrawport());
  95. }
  96.  
  97.  
  98.  
  99. /////////////////////////////////////////////////////////////////////////////
  100. // CMfc_mdiView
  101.  
  102. IMPLEMENT_DYNCREATE(CMfc_mdiView, CView)
  103.  
  104. BEGIN_MESSAGE_MAP(CMfc_mdiView, CView)
  105.     //{{AFX_MSG_MAP(CMfc_mdiView)
  106.     ON_WM_SIZE()
  107.     ON_WM_DESTROY()
  108.     ON_WM_MOUSEMOVE()
  109.     ON_WM_LBUTTONDOWN()
  110.     ON_WM_LBUTTONDBLCLK()
  111.     ON_WM_ACTIVATE()
  112.     ON_WM_PALETTECHANGED()
  113.     ON_WM_QUERYNEWPALETTE()
  114.     //}}AFX_MSG_MAP
  115. END_MESSAGE_MAP()
  116.  
  117. /////////////////////////////////////////////////////////////////////////////
  118. // CMfc_mdiView construction/destruction
  119.  
  120.  
  121. /////////////////////////////////////////////////////////////////////////////
  122. //
  123. CMfc_mdiView::CMfc_mdiView()
  124. : m_Scr(0), m_Dp(0), m_TimerID(0), m_Loc(0), m_DvProc(0)
  125. {
  126. }
  127.  
  128.  
  129. /////////////////////////////////////////////////////////////////////////////
  130. //
  131. //    OnSize()
  132. //
  133. //    If we have a screen object (m_Scr), call TscReset(), which resizes the
  134. //    screen and any of its drawports.  Note that no drawing is done at this
  135. //    time; this is because the WM_SIZE message causes a WM_PAINT message
  136. //    which the framework handles by calling the OnDraw() method.
  137. //
  138. void CMfc_mdiView::OnSize(UINT nType, int cx, int cy) 
  139. {
  140.     CView::OnSize(nType, cx, cy);
  141.     if(m_Scr)
  142.         TscReset(m_Scr);
  143. }
  144.  
  145.  
  146. /////////////////////////////////////////////////////////////////////////////
  147. //
  148. //    OnDraw()
  149. //
  150. //    The OnDraw() method, after checking that we have both a screen and a
  151. //    drawport, set the screen object for this view (m_Scr) to be the current
  152. //  screen, and then checks to see if    the drawport has been previously drawn.
  153. //  If it has not, then simply draw all of it.  More interesting is if it has,
  154. //  in which case we get the current    window message and pass that along with
  155. //    a pointer to a DataViews WINEVENT structure to the low-level graphics
  156. //  routine GRwe_convert().  This routine populates the WINEVENT structure
  157. //    with, among other things, the area (or region) of the drawport that needs
  158. //  to be updated.  Now we can more    efficiently redraw just that portion of
  159. //  the screen that needs to be redrawn.
  160. //
  161. void CMfc_mdiView::OnDraw(CDC* pDC)
  162. {
  163.     if(m_Scr && m_Dp)
  164.     {
  165.         TscSetCurrentScreen(m_Scr);  
  166.         if(TdpIsDrawn(m_Dp))
  167.         {
  168.             WINEVENT we;
  169.             GRwe_convert((ADDRESS)GetCurrentMessage(), &we);
  170.             TdpRedraw(m_Dp, &we.region, YES);
  171.         }
  172.          else
  173.              TdpDraw(m_Dp);
  174.          
  175.          TscFlush(m_Scr);
  176.     }
  177. }
  178.  
  179.  
  180.  
  181. /////////////////////////////////////////////////////////////////////////////
  182. // CMfc_mdiView diagnostics
  183.  
  184. #ifdef _DEBUG
  185. void CMfc_mdiView::AssertValid() const
  186. {
  187.     CView::AssertValid();
  188. }
  189.  
  190. void CMfc_mdiView::Dump(CDumpContext& dc) const
  191. {
  192.     CView::Dump(dc);
  193. }
  194.  
  195. CMfc_mdiDoc* CMfc_mdiView::GetDocument() // non-debug version is inline
  196. {
  197.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMfc_mdiDoc)));
  198.     return (CMfc_mdiDoc*)m_pDocument;
  199. }
  200. #endif //_DEBUG
  201.  
  202. /////////////////////////////////////////////////////////////////////////////
  203. // CMfc_mdiView message handlers
  204.  
  205.  
  206. /////////////////////////////////////////////////////////////////////////////
  207. //
  208. //    InstallTimer():
  209. //
  210. //    Checks for a previously installed timer, and if so, kills it first.
  211. //    We then install a new timer, passing the 'this' pointer through the
  212. //    nIDEvent (timer identification) field. The 'this' pointer is then cast
  213. //  to a CMfc_mdiView* in the callback UpdateDynamicsTimerProc() which
  214. //    then updates the DataViews view's dynamics.
  215. //
  216. void CMfc_mdiView::InstallTimer(UINT nTimeInterval) 
  217. {
  218.     if(m_TimerID)
  219.         KillTimer(m_TimerID);
  220.     m_TimerID = SetTimer((UINT)this, nTimeInterval,UpdateDynamicsTimerProc);
  221. }
  222.  
  223.  
  224. /////////////////////////////////////////////////////////////////////////////
  225. //
  226. void CMfc_mdiView::DisplayObjectType(OBJECT Ob)
  227. {
  228.   char* obType = 0;
  229.  
  230.   switch(VOobType(Ob))
  231.   {
  232.   case OT_ARC        : obType = "Arc"           ; break;
  233.   case OT_CIRCLE     : obType = "Circle"        ; break;
  234.   case OT_DG         : obType = "Graph"         ; break;
  235.   case OT_ELLIPSE    : obType = "Ellipse"       ; break;
  236.   case OT_ICON       : obType = "Icon"          ; break;
  237.   case OT_IMAGE      : obType = "Image"         ; break;
  238.   case OT_INPUT      : obType = "Input Object"  ; break;
  239.   case OT_LINE       : obType = "Line"          ; break;
  240.   case OT_POLYGON    : obType = "Polygon"       ; break;
  241.   case OT_RECTANGLE  : obType = "Rectangle"     ; break;
  242.   case OT_SUBDRAWING : obType = "Subdrawing"    ; break;
  243.   case OT_TEXT       : obType = "Hardware text" ; break;
  244.   case OT_VTEXT      : obType = "Vector text"   ; break;
  245.   case OT_SFTEXT     : obType = "Scalable font" ; break;
  246.   default            : obType = "Unknown"       ; break;
  247.   }
  248.  
  249.   CString msg;
  250.   msg.Format("Selected object type is: %s", obType);
  251.   AfxMessageBox((LPCTSTR)msg);
  252. }
  253.  
  254.  
  255. /////////////////////////////////////////////////////////////////////////////
  256. //
  257. BOOL CMfc_mdiView::SetupLoc(const MSG* msg) 
  258. {
  259.     if(m_Scr && m_Dp)
  260.     {
  261.         WINEVENT we;
  262.         TscSetCurrentScreen(m_Scr);  
  263.         GRwe_convert((ADDRESS)msg, &we);
  264.         return (BOOL)TloWinEventSetup(m_Loc,&we,m_Scr,m_Dp);
  265.     }
  266.     return FALSE;
  267. }
  268.  
  269.  
  270. /////////////////////////////////////////////////////////////////////////////
  271. //
  272. //    InitDV()
  273. //
  274. //
  275. BOOL CMfc_mdiView::InitDv(VIEW dvView) 
  276. {
  277.     RECTANGLE WholeWorld = { -16383, -16383, 16383, 16383};
  278.  
  279.     // Open the DataViews screen object...
  280.     m_Scr = TscOpenSet("W", (char*)0,
  281.                         V_WIN32_WINDOW_HANDLE, GetSafeHwnd(),
  282.                         V_WIN32_DOUBLE_BUFFER,TRUE,
  283.                         V_ACTIVE_CURSOR, V_END_OF_LIST);
  284.  
  285.     // ...check for any errors, such as licensing problems...
  286.     if(TscOpenError())
  287.     {
  288.         m_Scr = 0;
  289.         return FALSE;
  290.     }
  291.  
  292.   // ..get the DataViews driver default WinProc.  We'll use this later
  293.   // to handle special case messages...
  294.      GRget(V_WIN32_WINDOWPROC, &m_DvProc, V_END_OF_LIST);
  295.  
  296.   // ..create our location object for handling user input...
  297.   m_Loc = VOloCreate();
  298.  
  299.     // ..create the drawport...
  300.     m_Dp = TdpCreateStretch(m_Scr,dvView,0,&WholeWorld);
  301.  
  302.     /////////////////////////////////////////////////////////////////////////
  303.     //
  304.     //  ...or use this form to avoid distortion (see DV-Tools User's Guide
  305.     //  for discussion on drawport creation): 
  306.     //
  307.     //    m_Dp = TdpCreate(m_Scr,dvView,0,&WholeWorld);
  308.     //
  309.     /////////////////////////////////////////////////////////////////////////
  310.  
  311.  
  312.     // ...draw the drawport.  A technical aside: we really do not have make
  313.     // this call to TdpDraw(), as this would more naturally happen in the
  314.     // OnDraw() method.  However, in this particular example program, the
  315.     // effect we are aiming for is for the dynamic objects to appear instant-
  316.     // ly dynamic from the very start.  Since TdpDraw() must be called prior
  317.     // to calling TdpDrawNext() (the routine that actually updates dynamics),
  318.     // we need to call it now rather than later.
  319.     TdpDraw(m_Dp);
  320.  
  321.     // Now we are ready to open the view's data sources, read the first
  322.     // iteration of data and update the the drawport by calling TdpDrawNext()...
  323.     TviOpenData(dvView);
  324.     TviReadData(dvView);
  325.     TdpDrawNext(m_Dp);
  326.  
  327.     // ...and finally, start the timer process that will continuously update
  328.     // the view's dynamics.
  329.     InstallTimer();
  330.  
  331.     return TRUE;
  332. }
  333.  
  334.  
  335. /////////////////////////////////////////////////////////////////////////////
  336. //
  337. //    Clean up DataViews data structures owned by the CView, namely the screen
  338. //    and drawport.  The important thing here is that TscClose() needs to be
  339. //    called *before* the Window's window (m_hWnd) goes out of existence,
  340. //    otherwise, without a valid window handle, DataViews will not be able to
  341. //    properly clean up system resources it has allocated.
  342. //
  343. //    To that end, cleanup is done while processing the WM_DESTROY message
  344. //    (and before the base class OnDestroy() method), and not, as one might
  345. //    think at first glance, in the destructor, as it is too late by then.
  346. //
  347. void CMfc_mdiView::OnDestroy() 
  348. {
  349.     if(m_Dp)
  350.         TdpDestroy(m_Dp);
  351.  
  352.     if(m_Scr)
  353.         TscClose(m_Scr);
  354.  
  355.   if(m_Loc)
  356.     VOobDereference(m_Loc);
  357.  
  358.     CView::OnDestroy();
  359.     
  360.     if(m_TimerID)
  361.         KillTimer(m_TimerID);
  362. }
  363.  
  364.  
  365. /////////////////////////////////////////////////////////////////////////////
  366. //
  367. //                            Handling User Input
  368. //
  369. // Handling user input in this example means handling the mouse messages for
  370. // motion (WM_MOUSEMOVE), left button down (WM_LBUTTONDOWN), and left button
  371. // double clicks (ON_WM_LBUTTONDBLCLK).
  372. //
  373.  
  374.  
  375. void CMfc_mdiView::OnMouseMove(UINT nFlags, CPoint point) 
  376. {
  377.   if(SetupLoc(GetCurrentMessage()))
  378.     VUerHandleLocEvent(m_Loc);
  379. }
  380.  
  381. void CMfc_mdiView::OnLButtonDown(UINT nFlags, CPoint point) 
  382. {
  383.   if(SetupLoc(GetCurrentMessage()))
  384.     VUerHandleLocEvent(m_Loc);
  385. }
  386.  
  387. /////////////////////////////////////////////////////////////////////////////
  388. //
  389. //                        Double click Messages
  390. //
  391. // DataViews does not support doubleclick messages, but this method shows
  392. // how to take a double click message and convert it to a DataViews location
  393. // object that can be used to pop up a message box with the object's name...
  394. //
  395. void CMfc_mdiView::OnLButtonDblClk(UINT nFlags, CPoint point) 
  396. {
  397.     MSG fakeMsg;  // used to fool DataViews...
  398.   const MSG* realMsg = GetCurrentMessage();
  399.  
  400.   // Change the message type to be a left button down message
  401.      fakeMsg = *realMsg;
  402.      fakeMsg.message = WM_LBUTTONDOWN;
  403.  
  404.   SetupLoc((const MSG*)&fakeMsg);
  405.   OBJECT selectedOb = TloGetSelectedObject(m_Loc);
  406.   if(selectedOb)
  407.     DisplayObjectType(selectedOb);
  408. }
  409.  
  410.  
  411.  
  412. /////////////////////////////////////////////////////////////////////////////
  413. //
  414. //                        Special Case Messages
  415. //
  416. //  The following three message handlers handle the WM_ACTIVATE,
  417. //  WM_PALETTECHANGED, and WM_QUERYNEWPALETTE messages respectively.  These
  418. //  messages need to be special cased in order for the DataViews Windows
  419. //  driver to properly handle color palette changes.  This is done by
  420. //  simply calling the driver's own WinProc (passing in the particular window
  421. //  handle) and the message parameters.
  422.  
  423. void CMfc_mdiView::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
  424. {
  425.     CView::OnActivate(nState, pWndOther, bMinimized);
  426.     
  427.   // If our application has been activated, we want to tell the DataViews
  428.   // driver to select our colormap into the system palette...
  429.     const MSG* msg = GetCurrentMessage();
  430.     ::CallWindowProc((WNDPROC)m_DvProc,m_hWnd,msg->message,msg->wParam,msg->lParam);
  431. }
  432.  
  433. void CMfc_mdiView::OnPaletteChanged(CWnd* pFocusWnd) 
  434. {
  435.     CView::OnPaletteChanged(pFocusWnd);
  436.  
  437.   // In this case, some other application has changed the palette, so we need
  438.   // to tell the driver to re-select ours...
  439.     const MSG* msg = GetCurrentMessage();
  440.     ::CallWindowProc((WNDPROC)m_DvProc,m_hWnd,msg->message,msg->wParam,msg->lParam);
  441. }
  442.  
  443. BOOL CMfc_mdiView::OnQueryNewPalette() 
  444. {
  445.   // This is basically the same situation as with OnPaletteChanged() above...
  446.     const MSG* msg = GetCurrentMessage();
  447.     ::CallWindowProc((WNDPROC)m_DvProc,m_hWnd,msg->message,msg->wParam,msg->lParam);
  448.  
  449.   return CView::OnQueryNewPalette();
  450. }
  451.  
  452.